import 'dart:convert';
import 'dart:io';

import '../types/types.dart';

import 'package:http/http.dart';
import 'http_helper.dart';

import 'global_helper.dart';

Future<Map<String, int>> getHashtags() async {
  final Response response = await httpGet("/songs?type=all", null);
  final result = jsonDecode(response.body);

  final Map<String, int> resultMap = {};

  List tags = result["results"];
  for (int i = 0; i < tags.length; i++) {
    final Map tag = tags[i];

    String name = tag["name"];
    int id = tag["id"];

    resultMap[name] = id;
  }

  return resultMap;
}

Future<List<SongFetchModel>> fetchSongs(int hashtagId) async {
  final Response response =
      await httpGet("/songs?hashtags=$hashtagId&pageSize=99999", null);
  final result = jsonDecode(response.body);

  final List list = result["results"];
  return list
      .map<SongFetchModel>((map) => SongFetchModel.fromJson(map))
      .toList();
}

Future<String?> readResourceFile(fileName) async {
  var filePath = await getAppResourcePath() + fileName;
  var file = File(filePath);
  if (await file.exists()) {
    return await file.readAsString();
  }
  return null;
}

Future<File> writeResourceFile(fileName, content) async {
  var filePath = await getAppResourcePath() + fileName;
  var file = File(filePath);
  return file.writeAsString(content);
}

Future<List<SongFetchModel>> fetchAllSongs() async {
  var fileName = '/songs.json';
  var content = await readResourceFile(fileName);
  List<SongFetchModel> returnData(String content) {
    final result = jsonDecode(content);
    final List list = result["results"];
    return list
        .map<SongFetchModel>((map) => SongFetchModel.fromJson(map))
        .toList();
  }

  if (content != null) {
    return returnData(content);
  }

  final Response response =
      await httpGet("/songs?pageSize=99999&responseMode=light", null);

  await writeResourceFile(fileName, response.body);
  return returnData(response.body);
}

Future<List<TransitionFetchModel>> fetchTransitions() async {
  var fileName = '/transitions.json';
  var content = await readResourceFile(fileName);
  List<TransitionFetchModel> returnData(String content) {
    final result = jsonDecode(content);
    final List list = result["results"];
    return list
        .map<TransitionFetchModel>((map) => TransitionFetchModel.fromJson(map))
        .toList();
  }

  if (content != null) {
    return returnData(content);
  }

  final Response response = await httpGet("/transitions?pageSize=99999", null);
  await writeResourceFile(fileName, response.body);
  return returnData(response.body);
}

Future<List<FrameFetchModel>> fetchFrames() async {
  var fileName = '/frames.json';
  var content = await readResourceFile(fileName);
  List<FrameFetchModel> returnData(String content) {
    final result = jsonDecode(content);
    final List list = result["results"];
    return list
        .map<FrameFetchModel>((map) => FrameFetchModel.fromJson(map))
        .toList();
  }

  if (content != null) {
    return returnData(content);
  }
  final Response response = await httpGet("/frames?pageSize=99999", null);
  await writeResourceFile(fileName, response.body);
  return returnData(response.body);
}

Future<List<StickerFetchModel>> fetchStickers() async {
  var fileName = '/stickers.json';
  var content = await readResourceFile(fileName);
  List<StickerFetchModel> returnData(String content) {
    final result = jsonDecode(content);
    final List list = result["results"];
    return list
        .map<StickerFetchModel>((map) => StickerFetchModel.fromJson(map))
        .toList();
  }

  if (content != null) {
    return returnData(content);
  }
  final Response response = await httpGet("/stickers?pageSize=99999", null);
  await writeResourceFile(fileName, response.body);
  return returnData(response.body);
}

Future<List<FontFetchModel>> fetchFonts() async {
  var fileName = '/fonts.json';
  var content = await readResourceFile(fileName);
  List<FontFetchModel> returnData(String content) {
    final result = jsonDecode(content);
    final List list = result["results"];
    return list
        .map<FontFetchModel>((map) => FontFetchModel.fromJson(map))
        .toList();
  }

  if (content != null) {
    return returnData(content);
  }
  final Response response = await httpGet("/fonts?pageSize=99999", null);
  await writeResourceFile(fileName, response.body);
  return returnData(response.body);
}

Future<DownloadResourceResponse> downloadResource(
    String filename, String url) async {
  final appDir = await getAppResourcePath();

  File file = File("$appDir/$filename");
  if (await file.exists()) {
    return DownloadResourceResponse(filename, file);
  }
  final Response response = await httpGet(url, null);
  if (response.contentLength == 0) {
    throw Exception("ERR_RESOURCE_DOWNLOAD_FAILED");
  }

  await file.writeAsBytes(response.bodyBytes);
  return DownloadResourceResponse(filename, file);
}

Future<DownloadFontResponse> downloadFont(String fontFamily) async {
  final list = await fetchFonts();
  for (var element in list) {
    if (element.fontFamily.compareTo(fontFamily) == 0) {
      DownloadResourceResponse res =
          await downloadResource(element.source!.name, element.source!.url);
      return DownloadFontResponse(
          res.filename, res.file, base64.encode(await res.file.readAsBytes()));
    }
  }
  throw Exception("downloadFont FAILED!");

  // final Response response =
  //     await httpGet("/fonts?fontFamily=$fontFamily&pageSize=99999", null);
  // final result = jsonDecode(response.body);

  // final List list = result["results"];
  // if (list.isEmpty) throw Exception("ERR_FONT_NOT_FOUND");

  // for (int i = 0; i < list.length; i++) {
  //   final font = FontFetchModel.fromJson(list[i]);
  //   if (font.fontFamily.compareTo(fontFamily) == 0) {
  //     DownloadResourceResponse res =
  //         await downloadResource(font.source!.name, font.source!.url);
  //     return DownloadFontResponse(
  //         res.filename, res.file, base64.encode(await res.file.readAsBytes()));
  //   }
  // }

  // final source = FontFetchModel.fromJson(list[0]).source!;
  // DownloadResourceResponse res =
  //     await downloadResource(source.name, source.url);

  // return DownloadFontResponse(
  //     res.filename, res.file, base64.encode(await res.file.readAsBytes()));
}
